package org.example.user.service.impl;

import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson2.JSONObject;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import io.micrometer.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.example.common.config.BusinessException;
import org.example.common.enums.RedisCache;
import org.example.common.pojo.SysUser;
import org.example.user.dto.*;
import org.example.user.entity.*;
import org.example.user.mapper.*;
import org.example.user.service.MockSmsCodeService;
import org.example.user.vo.*;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.example.user.service.ISysUserService;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;


import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static cn.dev33.satoken.stp.StpUtil.stpLogic;

/**
 * 用户表 服务层实现。
 *
 * @author mybatis-flex-helper automatic generation
 * @since 1.0
 */
@Slf4j
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUserEntity> implements ISysUserService {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysRoleUserMapper sysRoleUserMapper;


    @Autowired
    SysDeptMapper sysDeptMapper;

    @Autowired
    SysAclMapper sysAclMapper;

    @Autowired
    SysRoleAclMapper sysRoleAclMapper;

    @Autowired
    CodeMapper codeMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    SysMenuMapper sysMenuMapper;

    @Autowired
    private SysUserRealnameAuthMapper sysUserRealnameAuthMapper;

    @Autowired
    private MockSmsCodeService smsCodeService;

    @Transactional
    @Override
    public int createUser(CreateUserDTO createUserDTO) {
        String password = createUserDTO.getPassword();
        password = BCrypt.hashpw(password, BCrypt.gensalt());
        createUserDTO.setPassword(password);

        SysUserEntity sysUserEntity = new SysUserEntity();
        BeanUtils.copyProperties(createUserDTO, sysUserEntity);
        sysUserEntity.setStatus(1);
        sysUserEntity.setIsDelete(0);

        //@TODO
        sysUserEntity.setCreatedBy("admin");
        sysUserEntity.setCreatedTime(new Date());

        sysUserMapper.insert(sysUserEntity);

        List<SysRoleUserEntity> list = new LinkedList<>();

        for(Long roleId : createUserDTO.getRoleIds()){
            SysRoleUserEntity sysRoleUserEntity = new SysRoleUserEntity();
            sysRoleUserEntity.setUserId(sysUserEntity.getId());
            sysRoleUserEntity.setRoleId(roleId);
            sysRoleUserEntity.setCreatedTime(new Date());
            list.add(sysRoleUserEntity);
        }

        return sysRoleUserMapper.insertBatch(list);

    }


    //登录
    @Override
    public LoginVO login(LoginDTO loginDTO){
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("username", loginDTO.getUsername());

        SysUserEntity sysUserEntity = sysUserMapper.selectOneByQuery(wrapper);

        if(sysUserEntity == null){
            throw new BusinessException("用户名不存在");
        }
        String password = loginDTO.getPassword();
        String encode = BCrypt.hashpw(password, BCrypt.gensalt());

        log.info("encode: " + encode);
        log.info("sysUserEntity.getPassword(): " + sysUserEntity.getPassword());
        if(!BCrypt.checkpw(loginDTO.getPassword(), sysUserEntity.getPassword())){
            throw new BusinessException("密码错误");
        }

        if(sysUserEntity.getStatus() == 0){
            throw new BusinessException("用户已禁用");
        }

        if(sysUserEntity.getIsDelete() == 1){
            throw new BusinessException("用户已删除");
        }

        SysUser user = new SysUser();
        user.setUsername(sysUserEntity.getUsername());
        user.setUserType(sysUserEntity.getUserType());
        user.setUserId(sysUserEntity.getId());

        StpUtil.login(sysUserEntity.getId());
        StpUtil.getSession().set("user", user);

        LoginVO loginVO = new LoginVO();
        loginVO.setUserEntity(sysUserEntity);
        loginVO.setAccessToken(StpUtil.getTokenValue());
        loginVO.setRefreshToken(StpUtil.getTokenValue());
        return loginVO;
    }

    //登出
    @Override
    public int logout() {
        StpUtil.logout();
        return 1;
    }

    //更新 用户信息
    @Override
    public int updateUser(UpdateDTO updateDTO){
        SysUserEntity sysUserEntity = sysUserMapper.selectOneById(updateDTO.getUserId());
        if(sysUserEntity == null){
            throw new BusinessException("用户不存在");
        }
        //检验部门有效性@TODO
      BeanUtils.copyProperties(updateDTO, sysUserEntity);

      QueryWrapper wrapper = new QueryWrapper();
      wrapper.eq("id", updateDTO.getUserId());
      sysUserMapper.updateByQuery(sysUserEntity, wrapper);

        //关联用户角色（先删除旧的在插入新的）
        QueryWrapper roleWrapper = new QueryWrapper();
        roleWrapper.eq("user_id", updateDTO.getUserId());
        sysRoleUserMapper.deleteByQuery(roleWrapper);

        List<SysRoleUserEntity> list = new LinkedList<>();
        Long [] roleIds = updateDTO.getRoleIds();
        for(Long roleId : roleIds){
            SysRoleUserEntity sysRoleUserEntity = new SysRoleUserEntity();
            sysRoleUserEntity.setUserId(updateDTO.getUserId());
            sysRoleUserEntity.setRoleId(roleId);
            sysRoleUserEntity.setCreatedTime(new Date());
            list.add(sysRoleUserEntity);
        }

        return sysRoleUserMapper.insertBatch(list);
    }

    //删除用户
    @Override
    public int deleteUser(Long userId){
        SysUserEntity sysUserEntity = sysUserMapper.selectOneById(userId);
        if(sysUserEntity == null){
            throw new BusinessException("用户不存在");
        }

        sysUserMapper.deleteById(userId);

        //清理登录session
        if (StpUtil.isLogin(userId)) {
            StpUtil.kickout(userId);
        }
        return 1;
    }

    //分页查询用户列表
    @Override
    public Page<SysUserVO> pageList(UserQueryDTO userQueryDTO) {

        //判断userQuesyDTO中的值是否为null.不为null的才构建查询条件
        QueryWrapper queryWrapper = new QueryWrapper();
        if(!StringUtils.isEmpty(userQueryDTO.getUsername())){
            queryWrapper.like(SysUserEntity::getUsername,userQueryDTO.getUsername());
        }
        if(!StringUtils.isEmpty(userQueryDTO.getRealName())){
            queryWrapper.like(SysUserEntity::getRealName, userQueryDTO.getRealName());
        }
        if(userQueryDTO.getDeptId() != null){
            queryWrapper.eq(SysUserEntity::getDeptId, userQueryDTO.getDeptId());
        }
        if(userQueryDTO.getStatus() != null){
            queryWrapper.eq(SysUserEntity::getStatus, userQueryDTO.getStatus());
        }


        Page<SysUserEntity> paginate = sysUserMapper.paginate(userQueryDTO.getPage(), userQueryDTO.getSize(), queryWrapper);


        List<SysUserEntity> records = paginate.getRecords();
        Set<Long> userIds = records.stream().map(SysUserEntity::getId).collect(Collectors.toSet());

        QueryWrapper queryWrapper2 = new QueryWrapper();
        queryWrapper2.in(SysRoleUserEntity::getUserId, userIds);

        List<SysRoleUserEntity> sysRoleUserEntities = sysRoleUserMapper.selectListByQuery(queryWrapper2);

        Map<Long,List<Long>> map = sysRoleUserEntities.stream()
                .collect(Collectors.groupingBy(SysRoleUserEntity::getUserId,Collectors.mapping(SysRoleUserEntity::getRoleId,Collectors.toList())));

        //paginate 转为  Page<SysUserVO>
        Page<SysUserVO> page = new Page<>();

        List<SysUserVO> list = new LinkedList<>();

        records.forEach(record -> {
            SysUserVO sysUserVO = new SysUserVO();
            BeanUtils.copyProperties(record, sysUserVO);

            Long userId = record.getId();
            List<Long> roleIds = map.get(userId);
            sysUserVO.setRoleIds(roleIds);
            list.add(sysUserVO);
        });

        page.setRecords(list);
        page.setTotalRow(paginate.getTotalRow());
        page.setTotalPage(paginate.getTotalPage());
        page.setPageNumber(paginate.getPageNumber());
        page.setPageSize(paginate.getPageSize());
        log.info("Page: {}, Size: {}", userQueryDTO.getPage(), userQueryDTO.getSize());

        return page;
    }

    //-----eg
    @Override
    public UserVO getUserVO(){
        UserVO userVO = sysUserMapper.selectUserVO(StpUtil.getLoginIdAsLong());
        //---------查权限-----------
        List<SysRoleEntity> roles = userVO.getRoles();
        List<Long> roleIds = roles.stream().map(SysRoleEntity::getId).collect(Collectors.toList());

        QueryWrapper wrapper = new QueryWrapper();
        wrapper.in(SysRoleUserEntity::getRoleId, roleIds);
        List<SysRoleAclEntity> sysRoleAclEntities = sysRoleAclMapper.selectListByQuery(wrapper);
        List<Long> aclIds = sysRoleAclEntities.stream().map(SysRoleAclEntity::getAclId).collect(Collectors.toList());

        List<SysAclEntity> sysAclEntityes = sysAclMapper.selectListByIds(aclIds);
        userVO.setRoles(roles);
        userVO.setPermissions(sysAclEntityes.stream().map(SysAclEntity::getCode).collect(Collectors.toList()));
        //----------------------------

        //查菜单
        QueryWrapper aclQueryWrapper = new QueryWrapper();
        aclQueryWrapper.in(SysMenuEntity::getAclId, aclIds)
                .or("acl_id is null");
        List<SysMenuEntity> sysMenuEntities = sysMenuMapper.selectListByQuery(aclQueryWrapper);
        List<UserInfoVO.MenuTreeVO>menuTreeVOS = this.buildTree(sysMenuEntities);
        userVO.setMenuList(menuTreeVOS);

        return userVO;
    }


    //获取用户认证信息
    @Override
    @RedisCache(key = "auth:user:{loginId}",expire = 30, timeUnit = TimeUnit.MINUTES, value = UserInfoVO.class)
    public UserInfoVO getUserAuthInfo() {
        UserInfoVO userInfoVO = new UserInfoVO();

        SysUserEntity sysUserEntity = sysUserMapper.selectOneById(StpUtil.getLoginIdAsLong());

        if(sysUserEntity == null) {
            throw new BusinessException("当前用户不存在");
        }

        userInfoVO.setUsername(sysUserEntity.getUsername());
        userInfoVO.setUserId(sysUserEntity.getId());
        userInfoVO.setRealName(sysUserEntity.getRealName());
        userInfoVO.setDeptId(sysUserEntity.getDeptId());

        SysDeptEntity sysDeptEntity = sysDeptMapper.selectOneById(sysUserEntity.getDeptId());
        if(sysDeptEntity != null) {
            userInfoVO.setDeptName(sysDeptEntity.getName());
        }
        /**
         * select * from sys_role_user su
         * left  join sys_role_acl rc on su.role_id = rc.role_id
         * left join sys_acl sa on  rc.acl_id = sa.id
         * where su.user_id = '1'
         *
         */
        //查权限
        List<CodeDTO> code = codeMapper.getCode();
        List<String>  premis = code.stream().map(CodeDTO::getCode).collect(Collectors.toList());
        userInfoVO.setPermissions(premis);

        //查角色
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq(SysRoleUserEntity::getUserId, StpUtil.getLoginIdAsLong());

        List<SysRoleUserEntity> sysRoleUserEntities = sysRoleUserMapper.selectListByQuery(queryWrapper);
        List<Long> roleIds = sysRoleUserEntities.stream().map(SysRoleUserEntity::getRoleId).collect(Collectors.toList());

        List<SysRoleEntity> sysRoleEntities = sysRoleMapper.selectListByIds(roleIds);
        List<String> roleNames = sysRoleEntities.stream().map(SysRoleEntity::getName).collect(Collectors.toList());
        userInfoVO.setRoles(roleNames);

        //查菜单
        Set<Long> aclSet = code.stream().map(CodeDTO::getAclId).collect(Collectors.toSet());

        QueryWrapper aclQueryWrapper = new QueryWrapper();
        aclQueryWrapper.in(SysMenuEntity::getAclId, aclSet)
                .or("acl_id is null");
        List<SysMenuEntity> sysMenuEntities = sysMenuMapper.selectListByQuery(aclQueryWrapper);

        //需要将 sysMenuEntities 转为树形结构的menuTreeVOS

        List<UserInfoVO.MenuTreeVO> menuTreeVOS = this.buildTree(sysMenuEntities);
        userInfoVO.setMenuTree(menuTreeVOS);

        return userInfoVO;

    }


    public List<UserInfoVO.MenuTreeVO> buildTree(List<SysMenuEntity> menus) {
        // 1. 获取所有根节点（parentId为0或null的菜单）
        List<UserInfoVO.MenuTreeVO> roots = menus.stream()
                .filter(menu -> menu.getParentId() == null || 0 == menu.getParentId())
                .map(this::convertToVO)
                .collect(Collectors.toList());

        // 2. 递归构建子节点
        roots.forEach(root -> findChildren(root, menus));

        return roots;
    }

    private void findChildren(UserInfoVO.MenuTreeVO parent, List<SysMenuEntity> allMenus) {
        List<UserInfoVO.MenuTreeVO> children = allMenus.stream()
                .filter(menu -> parent.getId().equals(menu.getParentId()))
                .map(this::convertToVO)
                .collect(Collectors.toList());

        parent.setChildren(children);
        children.forEach(child -> findChildren(child, allMenus)); // 递归处理子节点
    }

    private UserInfoVO.MenuTreeVO convertToVO(SysMenuEntity entity) {
        UserInfoVO.MenuTreeVO vo = new UserInfoVO.MenuTreeVO();
        vo.setId(entity.getId());
        vo.setName(entity.getName());
        vo.setPath(entity.getPath());
        vo.setIcon(entity.getIcon());
        vo.setComponent(entity.getPath());

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("title", entity.getName());
        jsonObject.put("icon", entity.getIcon());
        jsonObject.put("hidden", entity.getHidden());
        vo.setMeta(jsonObject);
        // 其他字段拷贝...
        return vo;
    }

    @Override
    public UserDetailVO getUserInfo(Long userId){
        SysUserEntity sysUserEntity = sysUserMapper.selectOneById(userId);
        UserDetailVO userDetailVO = new UserDetailVO();
        BeanUtils.copyProperties(sysUserEntity, userDetailVO);
        userDetailVO.setUserId(sysUserEntity.getId());

        SysDeptEntity sysDeptEntity = sysDeptMapper.selectOneById(sysUserEntity.getDeptId());
        if(sysDeptEntity != null) {
            userDetailVO.setDeptName(sysDeptEntity.getName());
        }
        /**
         * select * from sys_user su left join sys_role_user ru on su.id = ru.user_id
         * left join sys_role r on ru.role_id = r.id
         * where su.id = #{userId}
         */
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.select(SysRoleEntity::getName, SysRoleEntity::getId)
                .from(SysUserEntity.class)
                .leftJoin(SysRoleUserEntity.class).on(SysUserEntity::getId, SysRoleUserEntity::getUserId)
                .leftJoin(SysRoleEntity.class).on(SysRoleUserEntity::getRoleId, SysRoleEntity::getId)
                .where(SysUserEntity::getId).eq(userId);

        // 执行查询
        List<SysRoleEntity> roleList = sysRoleMapper.selectListByQuery(queryWrapper);

        // 4. 处理角色信息（适配图片中的UserDetailVO结构）
        if (!CollectionUtils.isEmpty(roleList)) {
            // 提取角色ID列表和名称列表
            List<Long> roleIds = roleList.stream()
                    .map(SysRoleEntity::getId)
                    .collect(Collectors.toList());

            List<String> roleNames = roleList.stream()
                    .map(SysRoleEntity::getName)
                    .collect(Collectors.toList());

            userDetailVO.setRoleIds(roleIds);
            userDetailVO.setRoleNames(roleNames);
        } else {
            // 确保空列表而不是null（符合图片中的列表类型）
            userDetailVO.setRoleIds(Collections.emptyList());
            userDetailVO.setRoleNames(Collections.emptyList());
        }
        log.info("userDetailVO: {}", userDetailVO);

        return userDetailVO;
    }


    //重置密码
    @Override
    public int resetPwd(Long userId, String password){
        SysUserEntity sysUserEntity = sysUserMapper.selectOneById(userId);
        if(sysUserEntity == null){
            throw new BusinessException("用户不存在");
        }
        //密码加密存储
        password = BCrypt.hashpw(password, BCrypt.gensalt());
        sysUserEntity.setPassword(password);
        sysUserEntity.setUpdatedTime(new Date());
        return sysUserMapper.update(sysUserEntity);
    }

    //获取个人信息
    @Override
    public ProfileVO getUserProfile(){
        ProfileVO profileVO = new ProfileVO();
        SysUserEntity sysUserEntity = sysUserMapper.selectOneById(StpUtil.getLoginIdAsLong());
        BeanUtils.copyProperties(sysUserEntity, profileVO);
        profileVO.setUserId(sysUserEntity.getId());
        profileVO.setName(sysUserEntity.getUsername());
        profileVO.setPhone(sysUserEntity.getMobile());

        //查询用户认证信息
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.select(SysUserRealnameAuthEntity::getAuthStatus,  SysUserRealnameAuthEntity::getIdCard)
                .from(SysUserRealnameAuthEntity.class)
                .where(SysUserRealnameAuthEntity::getUserId).eq(StpUtil.getLoginIdAsLong());
        SysUserRealnameAuthEntity sysUserRealnameAuthEntity = sysUserRealnameAuthMapper.selectOneByQuery(queryWrapper);

        if(sysUserRealnameAuthEntity != null){
            profileVO.setAuthStatus(sysUserRealnameAuthEntity.getAuthStatus());
            ProfileVO.AuthInfo authInfo = new ProfileVO.AuthInfo();
            authInfo.setRealName(sysUserEntity.getRealName());
            authInfo.setIdCard(sysUserRealnameAuthEntity.getIdCard());
            profileVO.setAuthInfo(authInfo);
        }
        return profileVO;
    }

    //更新个人信息
    @Override
    public int updateUserProfile(String name, String email){

        SysUserEntity sysUserEntity = sysUserMapper.selectOneById(StpUtil.getLoginIdAsLong());
        sysUserEntity.setUsername(name);
        sysUserEntity.setEmail(email);
        sysUserEntity.setUpdatedTime(new Date());
        return sysUserMapper.update(sysUserEntity);
    }

    //修改密码
    @Override
    public int updatePassword(String oldPassword, String newPassword){
        SysUserEntity sysUserEntity = sysUserMapper.selectOneById(StpUtil.getLoginIdAsLong());
        if(!BCrypt.checkpw(oldPassword, sysUserEntity.getPassword())){
            throw new BusinessException("原密码错误");
        }
        newPassword = BCrypt.hashpw(newPassword, BCrypt.gensalt());
        sysUserEntity.setPassword(newPassword);
        sysUserEntity.setUpdatedTime(new Date());

        sysUserMapper.update(sysUserEntity);
        StpUtil.logout();
        return 1;
    }

    //更换绑定手机号
    @Override
    public int updatePhone(String phone, String code){
        // 校验验证码
        if (!smsCodeService.verifyCode(phone, code)) {
            throw new BusinessException("验证码错误");
        }
       //检验手机号是否已被使用
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.select(SysUserEntity::getId)
                .from(SysUserEntity.class)
                .where(SysUserEntity::getMobile).eq(phone);
        SysUserEntity sysUserEntity = sysUserMapper.selectOneByQuery(queryWrapper);
        if(sysUserEntity != null){
            throw new BusinessException("手机号已被注册");
        }
        // 更新手机号
        sysUserEntity = sysUserMapper.selectOneById(StpUtil.getLoginIdAsLong());
        sysUserEntity.setMobile(phone);
        sysUserEntity.setUpdatedTime(new Date());
        //清除验证码
        smsCodeService.clearCode(phone);
        return sysUserMapper.update(sysUserEntity);
    }

    //刷新访问令牌
    public static void renewTimeout(String tokenValue, long timeout){
        stpLogic.renewTimeout(tokenValue, timeout);
    }
    @Override
    public String refreshToken(String refreshToken) {
        this.renewTimeout(refreshToken, 60 * 60 * 24 * 7);
        return StpUtil.getTokenValue();
    }

    //修改登录密码
    @Override
    public int changeLoginPassword(String oldPassword, String newPassword){
        return this.updatePassword(oldPassword, newPassword);
    }

    //短信验证码登录
    @Override
    public LoginVO smsLogin(String mobile, String smsCode){
        //校验验证码
        if(!smsCodeService.verifyCode(mobile, smsCode)){
            throw new BusinessException("验证码错误");
        }
        //校验手机号是否已被注册
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.select("*")
                .from(SysUserEntity.class)
                .where(SysUserEntity::getMobile).eq(mobile);
        SysUserEntity sysUserEntity = sysUserMapper.selectOneByQuery(queryWrapper);
        if(sysUserEntity == null){
            throw new BusinessException("手机号未注册");
        }
        //登录
        StpUtil.login(sysUserEntity.getId());
        LoginVO loginVO = new LoginVO();
        loginVO.setUserEntity(sysUserEntity);
        loginVO.setAccessToken(StpUtil.getTokenValue());
        loginVO.setRefreshToken(StpUtil.getTokenValue());
        return loginVO;
    }

}
